#include "videotranscoder.h"
#include <QDebug>
#include <QFile>
#include <QCryptographicHash>

/**
 * @brief 构造函数
 */
VideoTranscoder::VideoTranscoder(QObject *parent)
    : QObject(parent)
    , m_process(nullptr)
    , m_hasHardwareEncoder(false)
    , m_videoDuration(0)
{
    // 设置缓存目录
    m_cacheDir = QDir::homePath() + "/.cache/video_player/transcoded/";
    createCacheDir();
    
    // 检查依赖
    checkDependencies();
}

/**
 * @brief 析构函数
 */
VideoTranscoder::~VideoTranscoder()
{
    if (m_process) {
        stopTranscode();
        delete m_process;
    }
}

/**
 * @brief 检查FFmpeg依赖
 */
bool VideoTranscoder::checkDependencies()
{
    // 检查 ffmpeg（开发板路径：/usr/bin/ffmpeg）
    QProcess ffmpeg;
    ffmpeg.start("ffmpeg", QStringList() << "-version");
    
    if (!ffmpeg.waitForFinished(3000)) {
        qWarning() << "FFmpeg not found, transcoding disabled";
        return false;
    }
    
    QString output = ffmpeg.readAllStandardOutput();
    qInfo() << "FFmpeg detected:" << output.split('\n').first();
    
    // 检测硬件编码器支持
    QProcess checkEncoder;
    checkEncoder.start("ffmpeg", QStringList() << "-encoders");
    checkEncoder.waitForFinished(3000);
    QString encoders = checkEncoder.readAllStandardOutput();
    
    m_hasHardwareEncoder = encoders.contains("h264_v4l2m2m");
    
    if (m_hasHardwareEncoder) {
        qInfo() << "V4L2 hardware encoder (h264_v4l2m2m) available";
    } else {
        qInfo() << "Using software encoder (libopenh264 or libx264)";
    }
    
    return true;
}

/**
 * @brief 检测视频信息
 */
VideoInfo VideoTranscoder::detectVideoInfo(const QString &filePath)
{
    VideoInfo info;
    info.filePath = filePath;
    
    // 使用 ffmpeg -i 获取视频信息
    QProcess process;
    process.start("ffmpeg", QStringList() << "-i" << filePath);
    process.waitForFinished(5000);
    
    // ffmpeg 将信息输出到stderr
    QString output = process.readAllStandardError();
    
    // 解析视频信息
    info = parseVideoInfo(output, filePath);
    
    // 判断是否需要转码
    info.needsTranscode = needsTranscode(info);
    
    qDebug() << "Video info:" << filePath;
    qDebug() << "  Resolution:" << info.width << "x" << info.height;
    qDebug() << "  Codec:" << info.codec;
    qDebug() << "  Frame rate:" << info.frameRate;
    qDebug() << "  Bitrate:" << info.bitrate << "kbps";
    qDebug() << "  Duration:" << info.duration << "ms";
    qDebug() << "  Needs transcode:" << info.needsTranscode;
    
    return info;
}

/**
 * @brief 转码视频
 */
bool VideoTranscoder::transcodeVideo(const QString &inputPath, const QString &outputPath)
{
    if (m_process) {
        qWarning() << "Transcode already in progress";
        return false;
    }
    
    // 检查输入文件
    if (!QFile::exists(inputPath)) {
        emit errorOccurred("输入文件不存在");
        return false;
    }
    
    // 获取视频时长（用于计算进度）
    VideoInfo info = detectVideoInfo(inputPath);
    m_videoDuration = info.duration;
    m_currentOutputPath = outputPath;
    m_ffmpegOutput.clear();
    
    // 创建进程
    m_process = new QProcess(this);
    connect(m_process, &QProcess::readyReadStandardOutput, 
            this, &VideoTranscoder::onProcessReadyReadStandardOutput);
    connect(m_process, &QProcess::readyReadStandardError, 
            this, &VideoTranscoder::onProcessReadyReadStandardError);
    connect(m_process, static_cast<void(QProcess::*)(int, QProcess::ExitStatus)>(&QProcess::finished),
            this, &VideoTranscoder::onProcessFinished);
    
    // 构建转码命令
    QStringList args;
    args << "-i" << inputPath;
    args << "-y";  // 覆盖输出文件
    
    // 优先使用硬件编码器
    if (m_hasHardwareEncoder) {
        args << "-c:v" << "h264_v4l2m2m";
    } else {
        // 备用软件编码器
        args << "-c:v" << "libx264";
        args << "-preset" << "ultrafast";  // 快速编码
    }
    
    // 视频参数
    args << "-b:v" << QString::number(OPTIMAL_BITRATE) + "k";  // 视频码率
    args << "-s" << QString("%1x%2").arg(OPTIMAL_WIDTH).arg(OPTIMAL_HEIGHT);  // 分辨率
    args << "-r" << QString::number(OPTIMAL_FRAMERATE);  // 帧率
    
    // 音频参数
    args << "-c:a" << "aac";
    args << "-b:a" << "128k";
    args << "-ar" << "44100";
    
    // 输出文件
    args << outputPath;
    
    qDebug() << "Transcode command: ffmpeg" << args.join(" ");
    
    // 启动转码
    m_process->start("ffmpeg", args);
    
    if (!m_process->waitForStarted(3000)) {
        emit errorOccurred("启动FFmpeg失败");
        delete m_process;
        m_process = nullptr;
        return false;
    }
    
    qInfo() << "Transcode started:" << inputPath << "->" << outputPath;
    return true;
}

/**
 * @brief 获取转码后的缓存路径
 */
QString VideoTranscoder::getCachedVideoPath(const QString &originalPath)
{
    // 使用文件路径的MD5作为缓存文件名（避免路径过长问题）
    QByteArray hash = QCryptographicHash::hash(originalPath.toUtf8(), 
                                                 QCryptographicHash::Md5);
    QString fileName = hash.toHex() + "_optimized.mp4";
    
    return m_cacheDir + fileName;
}

/**
 * @brief 检查并清理缓存
 */
void VideoTranscoder::checkAndCleanCache()
{
    QDir cacheDir(m_cacheDir);
    if (!cacheDir.exists()) {
        return;
    }
    
    qint64 totalSize = 0;
    QFileInfoList files = cacheDir.entryInfoList(QDir::Files, QDir::Time);
    QDateTime now = QDateTime::currentDateTime();
    
    for (const QFileInfo &file : files) {
        totalSize += file.size();
        
        // 删除7天未访问的文件
        if (file.lastRead().daysTo(now) > CACHE_EXPIRE_DAYS) {
            QFile::remove(file.absoluteFilePath());
            qInfo() << "Auto-deleted old cache:" << file.fileName();
        }
    }
    
    // 如果缓存超过1GB，删除最旧的文件
    if (totalSize > MAX_CACHE_SIZE) {
        qInfo() << "Cache size exceeded" << MAX_CACHE_SIZE << "bytes, cleaning...";
        
        // 重新获取文件列表（按时间排序）
        files = cacheDir.entryInfoList(QDir::Files, QDir::Time);
        
        // 从最旧的开始删除，直到低于阈值
        for (int i = files.size() - 1; i >= 0 && totalSize > MAX_CACHE_SIZE * 0.8; --i) {
            QFile::remove(files[i].absoluteFilePath());
            totalSize -= files[i].size();
            qInfo() << "Deleted cache file:" << files[i].fileName();
        }
    }
    
    qInfo() << "Cache check completed. Total size:" << totalSize / 1024 / 1024 << "MB";
}

/**
 * @brief 清空所有缓存
 */
void VideoTranscoder::clearAllCache()
{
    QDir cacheDir(m_cacheDir);
    if (!cacheDir.exists()) {
        return;
    }
    
    QFileInfoList files = cacheDir.entryInfoList(QDir::Files);
    int count = 0;
    
    for (const QFileInfo &file : files) {
        if (QFile::remove(file.absoluteFilePath())) {
            count++;
        }
    }
    
    qInfo() << "Cleared" << count << "cache files";
}

/**
 * @brief 获取缓存大小
 */
qint64 VideoTranscoder::getCacheSize()
{
    QDir cacheDir(m_cacheDir);
    if (!cacheDir.exists()) {
        return 0;
    }
    
    qint64 totalSize = 0;
    QFileInfoList files = cacheDir.entryInfoList(QDir::Files);
    
    for (const QFileInfo &file : files) {
        totalSize += file.size();
    }
    
    return totalSize;
}

/**
 * @brief 停止当前转码
 */
void VideoTranscoder::stopTranscode()
{
    if (m_process && m_process->state() == QProcess::Running) {
        qInfo() << "Stopping transcode process...";
        m_process->kill();
        m_process->waitForFinished(3000);
        
        // 删除未完成的输出文件
        if (!m_currentOutputPath.isEmpty() && QFile::exists(m_currentOutputPath)) {
            QFile::remove(m_currentOutputPath);
        }
    }
}

// ========== 私有方法实现 ==========

/**
 * @brief 解析FFmpeg输出获取视频信息
 */
VideoInfo VideoTranscoder::parseVideoInfo(const QString &output, const QString &filePath)
{
    VideoInfo info;
    info.filePath = filePath;
    
    // 提取分辨率
    extractResolution(output, info.width, info.height);
    
    // 提取帧率
    info.frameRate = extractFrameRate(output);
    
    // 提取编码格式
    info.codec = extractCodec(output);
    
    // 提取码率
    info.bitrate = extractBitrate(output);
    
    // 提取时长
    info.duration = extractDuration(output);
    
    return info;
}

/**
 * @brief 判断是否需要转码
 */
bool VideoTranscoder::needsTranscode(const VideoInfo &info)
{
    // 分辨率不是640x480
    if (info.width != OPTIMAL_WIDTH || info.height != OPTIMAL_HEIGHT) {
        return true;
    }
    
    // 编码格式不是H.264
    if (!info.codec.contains("h264", Qt::CaseInsensitive) && 
        !info.codec.contains("avc", Qt::CaseInsensitive)) {
        return true;
    }
    
    // 帧率超过25fps
    if (info.frameRate > OPTIMAL_FRAMERATE) {
        return true;
    }
    
    // 码率超过2Mbps
    if (info.bitrate > 2000) {
        return true;
    }
    
    return false;
}

/**
 * @brief 创建缓存目录
 */
void VideoTranscoder::createCacheDir()
{
    QDir dir;
    if (!dir.exists(m_cacheDir)) {
        if (dir.mkpath(m_cacheDir)) {
            qInfo() << "Created cache directory:" << m_cacheDir;
        } else {
            qWarning() << "Failed to create cache directory:" << m_cacheDir;
        }
    }
}

/**
 * @brief 解析转码进度
 */
int VideoTranscoder::parseTranscodeProgress(const QString &output)
{
    if (m_videoDuration <= 0) {
        return 0;
    }
    
    // 解析 time=00:00:10.00 格式
    QRegularExpression timeRegex("time=(\\d+):(\\d+):(\\d+\\.\\d+)");
    QRegularExpressionMatch match = timeRegex.match(output);
    
    if (match.hasMatch()) {
        int hours = match.captured(1).toInt();
        int minutes = match.captured(2).toInt();
        double seconds = match.captured(3).toDouble();
        
        qint64 currentTime = (hours * 3600 + minutes * 60 + seconds) * 1000;
        int progress = static_cast<int>(currentTime * 100 / m_videoDuration);
        
        return qMin(progress, 100);
    }
    
    return 0;
}

/**
 * @brief 提取分辨率
 */
void VideoTranscoder::extractResolution(const QString &output, int &width, int &height)
{
    // 匹配格式: 1920x1080 或 1280x720
    QRegularExpression resRegex("(\\d+)x(\\d+)");
    QRegularExpressionMatch match = resRegex.match(output);
    
    if (match.hasMatch()) {
        width = match.captured(1).toInt();
        height = match.captured(2).toInt();
    }
}

/**
 * @brief 提取帧率
 */
int VideoTranscoder::extractFrameRate(const QString &output)
{
    // 匹配格式: 25 fps 或 29.97 fps
    QRegularExpression fpsRegex("(\\d+\\.?\\d*)\\s*fps");
    QRegularExpressionMatch match = fpsRegex.match(output);
    
    if (match.hasMatch()) {
        return static_cast<int>(match.captured(1).toDouble());
    }
    
    return 0;
}

/**
 * @brief 提取视频编码
 */
QString VideoTranscoder::extractCodec(const QString &output)
{
    // 匹配格式: Video: h264 或 Video: mpeg4
    QRegularExpression codecRegex("Video:\\s*(\\w+)");
    QRegularExpressionMatch match = codecRegex.match(output);
    
    if (match.hasMatch()) {
        return match.captured(1);
    }
    
    return "unknown";
}

/**
 * @brief 提取码率
 */
int VideoTranscoder::extractBitrate(const QString &output)
{
    // 匹配格式: bitrate: 1500 kb/s
    QRegularExpression bitrateRegex("bitrate:\\s*(\\d+)\\s*kb/s");
    QRegularExpressionMatch match = bitrateRegex.match(output);
    
    if (match.hasMatch()) {
        return match.captured(1).toInt();
    }
    
    return 0;
}

/**
 * @brief 提取时长
 */
qint64 VideoTranscoder::extractDuration(const QString &output)
{
    // 匹配格式: Duration: 00:02:30.00
    QRegularExpression durationRegex("Duration:\\s*(\\d+):(\\d+):(\\d+\\.\\d+)");
    QRegularExpressionMatch match = durationRegex.match(output);
    
    if (match.hasMatch()) {
        int hours = match.captured(1).toInt();
        int minutes = match.captured(2).toInt();
        double seconds = match.captured(3).toDouble();
        
        return (hours * 3600 + minutes * 60 + seconds) * 1000;
    }
    
    return 0;
}

// ========== 槽函数实现 ==========

/**
 * @brief 处理FFmpeg标准输出
 */
void VideoTranscoder::onProcessReadyReadStandardOutput()
{
    if (m_process) {
        QString output = m_process->readAllStandardOutput();
        m_ffmpegOutput += output;
        qDebug() << "FFmpeg stdout:" << output;
    }
}

/**
 * @brief 处理FFmpeg错误输出
 */
void VideoTranscoder::onProcessReadyReadStandardError()
{
    if (m_process) {
        QString output = m_process->readAllStandardError();
        m_ffmpegOutput += output;
        
        // 解析进度
        int progress = parseTranscodeProgress(output);
        if (progress > 0) {
            emit transcodeProgress(progress);
        }
    }
}

/**
 * @brief 处理进程完成
 */
void VideoTranscoder::onProcessFinished(int exitCode, QProcess::ExitStatus exitStatus)
{
    bool success = (exitCode == 0 && exitStatus == QProcess::NormalExit);
    
    if (success) {
        qInfo() << "Transcode completed successfully:" << m_currentOutputPath;
        emit transcodeProgress(100);
        emit transcodeFinished(true, m_currentOutputPath);
    } else {
        qWarning() << "Transcode failed with exit code:" << exitCode;
        qWarning() << "FFmpeg output:" << m_ffmpegOutput;
        
        // 删除失败的输出文件
        if (QFile::exists(m_currentOutputPath)) {
            QFile::remove(m_currentOutputPath);
        }
        
        emit errorOccurred("视频转码失败");
        emit transcodeFinished(false, "");
    }
    
    // 清理进程
    m_process->deleteLater();
    m_process = nullptr;
    m_currentOutputPath.clear();
    m_ffmpegOutput.clear();
}

